refactor: [#212] parameterize TofuTemplateRenderer by provider#213
Merged
josecelano merged 14 commits intomainfrom Dec 3, 2025
Merged
refactor: [#212] parameterize TofuTemplateRenderer by provider#213josecelano merged 14 commits intomainfrom
josecelano merged 14 commits intomainfrom
Conversation
- Add Hetzner provider support with OpenTofu templates (main.tf, variables.tfvars.tera) - Move cloud-init template to common folder shared by all providers - Add image field to HetznerConfig for OS image selection - Create Hetzner template wrappers (cloud_init, variables contexts) - Update TofuTemplateRenderer to accept ProviderConfig parameter - Ensure instance_info output format matches JSON parser expectations - All E2E tests pass including full deployment workflow
- Add HetznerVariablesRenderingFailed error variant for proper error propagation - Remove profile_name() from Environment - provider-specific data accessed via provider_config() - Update TofuTemplateRenderer to extract profile_name from ProviderConfig when needed - Add tera_error_chain() helper to display full Tera error chains including root cause - Update TemplateEngineError to include source error messages in Display The error messages now show the actual root cause: Before: 'Provider ... is not yet supported for template rendering' After: 'Failed to render Hetzner variables template: ... Variable `x` not found'
Replace LXD-specific troubleshooting commands with generic provider-neutral instructions across all error help messages. Files updated: - src/application/command_handlers/provision/errors.rs - src/application/command_handlers/destroy/errors.rs - src/application/command_handlers/configure/errors.rs - src/presentation/controllers/provision/errors.rs - src/presentation/controllers/destroy/errors.rs - src/presentation/controllers/configure/errors.rs - src/adapters/ssh/error.rs - src/bootstrap/help.rs Changes: - Remove 'lxc list', 'lxc exec', 'lxc version' commands from generic help - Replace with 'use your provider tools' or 'using provider tools' - Update paths like 'build/<env>' to 'build/<env>/tofu/<provider>' - Keep provider-specific guidance only where it applies to that provider - Update tests to check for 'provider' instead of 'lxc list'
- Simplify docs/user-guide/providers/README.md to be just an index - Refactor LXD provider guide to focus only on LXD-specific config - Refactor Hetzner provider guide to focus only on Hetzner-specific config - Create new docs/tech-stack/ssh-keys.md for SSH key documentation - Link to existing tech guides instead of duplicating content - Remove duplicated command steps (already in quick-start.md) - Remove made-up command outputs
- Create providers/lxd and providers/hetzner modules
- Move wrappers from template/wrappers to providers/{lxd,hetzner}/wrappers
- Remove empty template/wrappers directory
- Update all import paths to use new providers structure
New structure:
template/
├── common/renderer/ (shared template rendering)
└── providers/
├── lxd/wrappers/ (LXD-specific templates)
└── hetzner/wrappers/ (Hetzner-specific templates)
Since we use the same cloud-init template (templates/tofu/common/cloud-init.yml.tera) for all providers, there's no need for duplicate wrappers. - Move cloud_init wrapper to common/wrappers/cloud_init - Remove duplicate wrappers from providers/lxd and providers/hetzner - Update imports in cloud_init renderer to use common wrapper - Add notes in provider wrappers about shared cloud-init location This follows the one-to-one relationship between Tera templates and wrappers: - Common template → common wrapper - Provider-specific template → provider-specific wrapper
The VariablesTemplateError type was duplicated in both LXD and Hetzner provider variable wrappers. This extracts it to a shared location. - Create common/wrappers/errors.rs with shared VariablesTemplateError - Re-export VariablesTemplateError from both provider variable modules - Update common/wrappers/mod.rs to export the errors module This reduces code duplication while maintaining backward compatibility with existing imports from provider modules.
Extract TofuTemplateRenderer and rename ProvisionTemplateError to TofuTemplateRendererError for better naming alignment. Changes: - Create tofu_template_renderer.rs with TofuTemplateRenderer struct and TofuTemplateRendererError enum (moved from mod.rs) - Rename ProvisionTemplateError to TofuTemplateRendererError - Add deprecated type alias for backward compatibility - Update all imports to use the new error type name - Move all unit tests to the new module file The rename follows Rust conventions where error types are named after the type that produces them (TofuTemplateRenderer -> TofuTemplateRendererError).
Extract CloudInitTemplate and VariablesTemplate types to their own module files for better code organization and separation of concerns. Changes: - Extract CloudInitTemplate from common/wrappers/cloud_init/mod.rs to cloud_init_template.rs - Extract VariablesTemplate from providers/hetzner/wrappers/variables/mod.rs to variables_template.rs - Extract VariablesTemplate from providers/lxd/wrappers/variables/mod.rs to variables_template.rs - Move all associated unit tests with each type Each mod.rs now contains only module declarations and re-exports, following the pattern established in previous commits.
Remove the deprecated ProvisionTemplateError type alias and all its re-exports throughout the module hierarchy. The alias was introduced for backward compatibility during the rename to TofuTemplateRendererError. Changes: - Remove deprecated type alias from common/renderer/mod.rs - Remove re-exports from template/mod.rs and common/mod.rs - Remove re-export from tofu/mod.rs - Update docs/codebase-architecture.md to use TofuTemplateRendererError All code now uses TofuTemplateRendererError directly.
The OPENTOFU_SUBFOLDER constant was hardcoded to 'tofu/lxd' in production code, but was only used by LXD-specific E2E tests. This violates the principle that production code should not contain provider-specific constants. Changes: - Moved constant from src/infrastructure/external_tools/tofu/mod.rs to src/testing/e2e/mod.rs - Renamed from OPENTOFU_SUBFOLDER to LXD_OPENTOFU_SUBFOLDER for clarity about its provider-specific purpose - Updated all 3 test files that use it: - container.rs - Services dependency injection - context.rs - TestContext drop cleanup - preflight_cleanup.rs - cleanup_opentofu_infrastructure
The build_template_path function in CloudInitTemplateRenderer used a hardcoded 'tofu/common' string. This commit extracts it to a named constant COMMON_TEMPLATES_PATH for better clarity and maintainability. This follows the pattern of extracting magic strings to named constants for improved code readability and self-documentation.
Previously, when a command's working directory didn't exist, the error was 'No such file or directory (os error 2)' which could be confused with the command binary not being found. Now we check if the working directory exists before running the command and return a clear WorkingDirectoryNotFound error with the path, making it obvious what's missing.
- tofu_build_dir_for_provider now takes Provider enum instead of &str
- Removed hardcoded LXD-specific tofu_build_dir method from InternalConfig
- EnvironmentContext::tofu_build_dir() now uses the environment's
actual provider to determine the correct build directory path
This ensures the correct tofu build directory is used for each provider
(e.g., build/{env}/tofu/lxd vs build/{env}/tofu/hetzner).
Member
Author
|
ACK 24c8d33 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR fixes the hardcoded LXD provider path in
tofu_build_dir()which was causing Hetzner provisioning to fail because it was looking for templates inbuild/{env}/tofu/lxdinstead ofbuild/{env}/tofu/hetzner.Changes
Error Handling Improvements
WorkingDirectoryNotFounderror variant toCommandErrorfor clearer error messages when the working directory doesn't existProvider-Parameterized Tofu Build Directory
tofu_build_dir_for_providerto acceptProviderenum instead of&strfor type safetytofu_build_dir()method fromInternalConfigEnvironmentContext::tofu_build_dir()now uses the environment's actual provider to determine the correct build pathTesting
build/hetzner-test/tofu/hetzner/Related Issue
Closes #212